<template>
  <div style="border: 1px solid #ccc">
    <Toolbar
      :default-config="toolbarConfig"
      :editor="editorRef"
      :mode="mode"
      style="border-bottom: 1px solid #ccc"
    />
    <Editor
      v-model="contentValue"
      :default-config="editorConfig"
      :mode="mode"
      :style="editorStyle"
      @on-change="handleChange"
      @on-created="handleCreated"
    />
  </div>
</template>
<script setup>
import { useMessage } from "@/hooks/message";
import "@wangeditor/editor/dist/css/style.css"; // 引入 css
import {
  onBeforeUnmount,
  ref,
  shallowRef,
  onMounted,
  nextTick,
  watch
} from "vue";
import { Editor, Toolbar } from "@wangeditor/editor-for-vue";
import axios from "axios";
import { getTokenValue } from "@/utils/auth";

const { VITE_API_URL } = import.meta.env;
let apiBaseUrl = VITE_API_URL;

// 初始值
const props = defineProps({
  initValue: {
    type: String,
    default: ""
  },
  height: {
    type: Number,
    default: 380
  },
  fileTypeCode: {
    type: String,
    default: "100103"
  }
});

const emits = defineEmits(["change"]);
const mode = ref("default");

const editorStyle = ref({
  width: "100%",
  height: props.height + "px",
  "overflow-y": "hidden"
});

// 编辑器实例，必须用 shallowRef
let editorRef = null;

// 内容 HTML
const contentValue = ref("");

// 模拟 ajax 异步获取内容
onMounted(() => {
  nextTick(() => {
    // 界面节点更新完以后再修改值。
    contentValue.value = props.initValue;
  });
});

onBeforeMount(() => {
  editorRef = shallowRef();
});

onBeforeUnmount(() => {
  handleDestory();
});

const toolbarConfig = {
  // 富文本手动插入工具栏
  insertKeys: {
    index: 22, // 自定义插件在工具栏显示的位置
    keys: ["uploadAttachment"] // 查看名称
  }
};

const editorConfig = {
  placeholder: "请输入内容...", // 配置默认提示
  readOnly: false,
  hoverbarKeys: {
    attachment: {
      menuKeys: ["downloadAttachment"] // “下载附件”菜单
    }
  },
  MENU_CONF: {
    uploadAttachment: {
      async customUpload(file, insertFn) {
        // 文件上传
        const formData = new FormData();
        formData.set("file", file);

        formData.set("storageMode", "minio");
        formData.set("fileTypeCode", props.fileTypeCode);
        formData.set("fileName", file.name);
        formData.set("fileFlag", "0");
        formData.set("fileSize", file.size);
        formData.set("type", file.type);

        // 这里根据自己项目封装情况，设置上传地址
        const token = getTokenValue();
        axios.defaults.headers.common["Authorization"] = `Bearer ${token}`;
        const result = await axios.post(
          `${apiBaseUrl}/admin/file/upload`,
          formData
        );
        // 插入到富文本编辑器中，主意这里的三个参数都是必填的
        insertFn(file.name, result.data.data.storageFileUrl, file.name);
      }
    },
    // 配置上传服务器地址
    uploadImage: {
      // 小于该值就插入 base64 格式（而不上传），默认为 0
      base64LimitSize: 5 * 1024, // 5kb
      // 单个文件的最大体积限制，默认为 2M
      maxFileSize: 3 * 1024 * 1024, // 1M
      // // 最多可上传几个文件，默认为 100
      maxNumberOfFiles: 3,
      // 选择文件时的类型限制，默认为 ['image/*'] 。如不想限制，则设置为 []
      allowedFileTypes: ["image/*"],
      // 自定义上传
      async customUpload(file, insertFn) {
        // 文件上传
        const formData = new FormData();
        formData.set("file", file);
        formData.set("storageMode", "minio");
        formData.set("fileTypeCode", props.fileTypeCode);
        formData.set("fileName", file.name);
        formData.set("fileFlag", "0");
        formData.set("fileSize", file.size);
        formData.set("type", file.type);

        // 这里根据自己项目封装情况，设置上传地址
        const token = getTokenValue();
        axios.defaults.headers.common["Authorization"] = `Bearer ${token}`;
        const result = await axios.post(
          `${apiBaseUrl}/admin/file/upload`,
          formData
        );
        // 插入到富文本编辑器中，主意这里的三个参数都是必填的
        if (result.data.code && result.data.code === 200) {
          insertFn(result.data.data.storageFileUrl, file.name, file.name);
        } else {
          useMessage().error(result.data.msg);
        }
      }
    }
  }
};

// 组件销毁时，也及时销毁编辑器
const handleDestory = () => {
  const editor = editorRef.value;
  if (editor == null) return;
  editor.destroy();
};

const handleCreated = editor => {
  editorRef.value = editor; // 创建富文本编辑器
};

const handleChange = info => {
  emits("change", info.children, contentValue.value);
};
watch(
  () => props.initValue,
  value => {
    // 父组件获取初始值
    contentValue.value = value;
  }
);
</script>
